package com.edaoe.module.api.admin;

import com.edaoe.common.Options;
import com.edaoe.common.Ret;
import com.edaoe.model.*;
import com.edaoe.thread.LuceneThread;
import com.edaoe.util.*;
import com.jfinal.kit.HashKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;

import java.util.List;

public class ApiAdminService {
    private static final String SEPARATOR = "、";

    public void clearExpiredAuthcode(){
        Authcode.dao.clearExpired();
    }

    public void rebuildIndex(){
        Options options=Options.getInstance();
        options.setMaintenance(true);
        List<User> users=User.dao.findAll();
        for (User user : users) {
            LuceneUtil.deleteAll(user.getId());
        }
        LuceneUtil.deleteAll(0);
        List<Article> articles=Article.dao.findByType(Article.TYPE_STANDARD);
        for (Article article : articles) {
            LuceneUtil.add(article.getUserId(),article.getId(),article.getTitle()+HtmlUtil.cleanHtmlTag(article.getHtmlContent()));
        }
        options.setMaintenance(false);
    }

    public Ret login(String username, String password, String captcha, String captchaToken) {
        if (!captcha.equalsIgnoreCase(EncrypAESUtil.decrypt(captchaToken)))
            return Ret.error(1001);
        User user = User.dao.findByUsername(username);
        if (user == null)
            return Ret.error(1002);
        if (!HashKit.md5(password + user.getSalt()).equals(user.getPassword()))
            return Ret.error(1003);
        String code;
        Authcode authcode = Authcode.dao.findByUserId(user.getId());
        if (authcode == null) {
            code = StrKit.getRandomUUID();
            new Authcode()
                    .setCode(code)
                    .setType(Authcode.TYPE_LOGIN)
                    .setExpireTime(DateUtil.getTwoClockTomorrow())
                    .setUserId(user.getId())
                    .save();
        } else {
            code = authcode.getCode();
        }
        return Ret.ok("authcode", code)
                .set("nickname", user.getNickname())
                .set("avatar", user.getAvatar());
    }

    public Ret articles(long userId, int pageNumber, int pageSize) {
        Page<Article> articlePage = Article.dao.paginateByUserId(userId, pageNumber, pageSize);
        List<Article> articles = articlePage.getList();
        for (Article article : articles) {
            List<String> categoryNames = ArticleCategory.dao.findCategoryNamesByArticleId(article.getId());
            article.put("categoryNames", CollectionUtil.join(categoryNames, SEPARATOR));
            List<String> tagNames = ArticleTag.dao.findTagNamesByArticleId(article.getId());
            article.put("tagNames", CollectionUtil.join(tagNames, SEPARATOR));
        }
        return Ret.ok("total", articlePage.getTotalRow())
                .set("articles", articles);
    }

    public Ret deleteArticle(long userId, long articleId) {
        if (Options.getInstance().isMaintenance())
            return Ret.error(1004);
        Article article = Article.dao.findById(articleId);
        if (article.getUserId() != userId)
            return Ret.error(1005);
        article.delete();
        LuceneThread luceneThread=new LuceneThread(userId,articleId);
        new Thread(luceneThread).start();
        return Ret.ok();
    }

    public Ret editArticle(long userId, long articleId) {
        Article article = Article.dao.findById(articleId);
        if (article.getUserId() != userId)
            return Ret.error(1005);
        List<String> categoryNames = ArticleCategory.dao.findCategoryNamesByArticleId(articleId);
        List<String> tagNames = ArticleTag.dao.findTagNamesByArticleId(articleId);
        return Ret.ok("title", article.getTitle())
                .set("type", article.getType().toString())
                .set("mdContent", article.getMdContent())
                .set("categoryNames", categoryNames)
                .set("tagNames", tagNames);
    }

    public Ret getCategories(long userId) {
        List<Category> categories = Category.dao.findByUserId(userId);
        return Ret.ok("categories", categories);
    }

    public Ret getTags(long userId) {
        List<Tag> tags = Tag.dao.findByUserId(userId);
        return Ret.ok("tags", tags);
    }

    public Ret saveArticle(long userId, Long articleId, String title, int type, String mdContent, String htmlContent,
                           Long[] categoryIds, String[] categoryNames, Long[] tagIds, String[] tagNames) {
        if (Options.getInstance().isMaintenance())
            return Ret.error(1004);
        String text = HtmlUtil.cleanHtmlTag(htmlContent);
        String abstractText = text.length() > 200 ? text.substring(0, 200) + "..." : text;
        Article article = new Article()
                .setTitle(title)
                .setAbstract(abstractText)
                .setHtmlContent(htmlContent)
                .setMdContent(mdContent)
                .setType(type)
                .setUserId(userId);
        if (articleId == null) {
            article.save();
            LuceneThread luceneThread = new LuceneThread(userId, article.getId(), title+text, LuceneThread.TYPE_ADD);
            new Thread(luceneThread).start();
        } else {
            if (Article.dao.findById(articleId).getUserId() != userId)
                return Ret.error(1005);
            article.setId(articleId).update();
            LuceneThread luceneThread = new LuceneThread(userId, article.getId(), title+text, LuceneThread.TYPE_UPDATE);
            new Thread(luceneThread).start();
            ArticleCategory.dao.deleteByArticleId(articleId);
            ArticleTag.dao.deleteByArticleId(articleId);
        }
        if(categoryIds!=null){
            for (int i = 0; i < categoryIds.length; i++) {
                long categoryId = categoryIds[i];
                if (categoryId == 0) {
                    Category category = new Category()
                            .setName(categoryNames[i])
                            .setUserId(userId);
                    category.save();
                    categoryId = category.getId();
                }
                new ArticleCategory()
                        .setArticleId(article.getId())
                        .setCategoryId(categoryId)
                        .save();
            }
        }
        if (tagIds!=null){
            for (int i = 0; i < tagIds.length; i++) {
                Long tagId = tagIds[i];
                if (tagId == 0) {
                    Tag tag = new Tag()
                            .setName(tagNames[i])
                            .setUserId(userId);
                    tag.save();
                    tagId = tag.getId();
                }
                new ArticleTag()
                        .setArticleId(article.getId())
                        .setTagId(tagId)
                        .save();
            }
        }
        return Ret.ok();
    }

    public Ret categories(long userId, int pageNumber, int pageSize) {
        Page<Category> categoryPage=Category.dao.paginateByUserId(userId,pageNumber,pageSize);
        List<Category> categories=categoryPage.getList();
        for (Category category : categories) {
            category.put("articleCount",ArticleCategory.dao.countByCategoryId(category.getId()));
        }
        return Ret.ok("total",categoryPage.getTotalRow())
                .set("categories",categories);
    }

    public Ret deleteCategory(long userId, long categoryId) {
        Category category=Category.dao.findById(categoryId);
        if (category.getUserId()!=userId)
            return Ret.error(1005);
        category.delete();
        return Ret.ok();
    }

    public Ret saveCategory(long userId, Long categoryId, String name) {
        if (categoryId==null){
            new Category()
                    .setName(name)
                    .setUserId(userId)
                    .save();
        }else{
            Category category=Category.dao.findById(categoryId);
            if (category.getUserId()!=userId)
                return Ret.error(1005);
            category.setName(name).update();
        }
        return Ret.ok();
    }

    public Ret tags(long userId, int pageNumber, int pageSize) {
        Page<Tag> tagPage=Tag.dao.paginateByUserId(userId,pageNumber,pageSize);
        List<Tag> tags=tagPage.getList();
        for (Tag tag : tags) {
            tag.put("articleCount",ArticleTag.dao.countByTagId(tag.getId()));
        }
        return Ret.ok("total",tagPage.getTotalRow())
                .set("tags",tags);
    }

    public Ret deleteTag(long userId, long tagId) {
        Tag tag=Tag.dao.findById(tagId);
        if (tag.getUserId()!=userId)
            return Ret.error(1005);
        tag.delete();
        return Ret.ok();
    }

    public Ret saveTag(long userId, Long tagId, String name) {
        if (tagId==null){
            new Tag()
                    .setName(name)
                    .setUserId(userId)
                    .save();
        }else{
            Tag tag=Tag.dao.findById(tagId);
            if (tag.getUserId()!=userId)
                return Ret.error(1005);
            tag.setName(name).update();
        }
        return Ret.ok();
    }

}
